<template>
  <div ref="domRef" class="dom-wrapper"></div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import * as SceneUtils from 'three/addons/utils/SceneUtils.js';
import * as THREE from 'three';
import { addCamera, addFloor, addSKYBox } from '@/hooks/helper';
let scene: THREE.Scene;
let controls: OrbitControls;
let camera: THREE.PerspectiveCamera;
let renderer: THREE.WebGLRenderer;

const domRef = ref(null);
const init = (warpDom: HTMLElement) => {
  const SCREEN_WIDTH = warpDom.clientWidth;
  const SCREEN_HEIGHT = warpDom.clientHeight;
  scene = new THREE.Scene();
  camera = addCamera(scene, SCREEN_WIDTH, SCREEN_HEIGHT);
  // addFloor(scene);
  addSKYBox(scene);

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
  warpDom.appendChild(renderer.domElement);
  controls = new OrbitControls(camera, renderer.domElement);

  ////////////
  // CUSTOM //
  ////////////
  // must enable shadows on the renderer
  renderer.shadowMap.enabled = true;

  const spotlight = new THREE.SpotLight(0xffff00);
  spotlight.position.set(-60, 150, -30);
  spotlight.shadow.camera.visible = true;
  spotlight.intensity = 2;
  // must enable shadow casting ability for the light
  spotlight.castShadow = true;
  scene.add(spotlight);
  // add pointLightHelper 辅助线
  let pointLightHelper = new THREE.SpotLightHelper(spotlight, 0xffff00);
  scene.add(pointLightHelper);

  const spotlight2 = new THREE.SpotLight(0xff0000);
  spotlight2.position.set(60, 150, -60);
  spotlight2.shadow.camera.visible = true;
  spotlight2.intensity = 2;
  spotlight2.castShadow = true;
  scene.add(spotlight2);

  pointLightHelper = new THREE.SpotLightHelper(spotlight2, 0xff0000);
  scene.add(pointLightHelper);

  const spotlight3 = new THREE.SpotLight(0x0000ff);
  spotlight3.position.set(150, 80, -100);
  spotlight3.shadow.camera.visible = true;
  spotlight3.intensity = 2;
  spotlight3.castShadow = true;
  scene.add(spotlight3);

  // change the direction this spotlight is facing
  const lightTarget = new THREE.Object3D();
  lightTarget.position.set(150, 10, -100);
  scene.add(lightTarget);
  spotlight3.target = lightTarget;

  pointLightHelper = new THREE.SpotLightHelper(spotlight3, 0x0000ff);
  scene.add(pointLightHelper);

  // scene.add(pointLightHelper);
  // pointLightHelper = new THREE.SpotLightHelper(spotlight2, 'white');
  // scene.add(pointLightHelper);
  // pointLightHelper = new THREE.SpotLightHelper(spotlight, 'green');
  // scene.add(spotlight);

  // floor: mesh to receive shadows
  const floorTexture = new THREE.TextureLoader().load('images/checkerboard.jpg');
  floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
  floorTexture.repeat.set(10, 10);
  // Note the change to Lambert material.
  const floorMaterial = new THREE.MeshLambertMaterial({ map: floorTexture, side: THREE.DoubleSide });
  const floorGeometry = new THREE.PlaneGeometry(1000, 1000, 100, 100);
  const floor = new THREE.Mesh(floorGeometry, floorMaterial);
  floor.position.y = -0.5;
  floor.rotation.x = Math.PI / 2;
  // Note the mesh is flagged to receive shadows
  floor.receiveShadow = true;
  scene.add(floor);

  // cube: mesh to cast shadows
  const cubeGeometry = new THREE.BoxGeometry(50, 50, 50);
  const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0x888888 });
  const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
  cube.position.set(0, 50, 0);
  // Note that the mesh is flagged to cast shadows
  cube.castShadow = true;
  scene.add(cube);

  // create "light-ball" meshes
  const sphereGeometry = new THREE.SphereGeometry(10, 16, 8);

  let wireframeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: true, transparent: true });

  const shape = new THREE.Mesh(sphereGeometry, wireframeMaterial);
  shape.position.copy(spotlight.position);
  scene.add(shape);

  // wireframeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true, transparent: true });
  // const shape1 = new THREE.Mesh(sphereGeometry, [darkMaterial, wireframeMaterial]);
  // shape1.position.copy(spotlight2.position);
  // scene.add(shape1);

  // wireframeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff, wireframe: true, transparent: true });
  // const shape2 = new THREE.Mesh(sphereGeometry, [darkMaterial, wireframeMaterial]);
  // shape2.position.copy(spotlight3.position);
  // scene.add(shape2);
};
const render = () => {
  renderer.render(scene, camera);
};
const animate = () => {
  requestAnimationFrame(animate);
  render();
};
onMounted(() => {
  if (domRef.value) {
    init(domRef.value);
    animate();
  }
});
</script>

<style scoped>
.dom-wrapper {
  width: 100%;
  height: 100%;
}
</style>
